var SoundSystem:ISoundSystem=nil;
SoundGeometry:ISoundGeometry=nil;
Reverb:IReverb=nil;

function luaToSoundHandle(l:lua_state; i:integer):soundhandle; cdecl;
begin
if lua_isuserdata(l, i) then
result := soundhandle(lual_checkudata(l, i, 'soundHandle')^) else result := 0;
end;

procedure luaPushSoundHandle(l:lua_state; h:soundhandle); cdecl;
var p:^soundhandle;
begin
p := lua_newUserData(l, sizeof(SoundHandle));
p^ := h;
lual_getmetatable(l, 'soundHandle');
lua_setmetatable(l, -2);
end;

function luass_playSound3d(L: lua_state): Integer; cdecl;
var v_paused : boolean;
begin
  if lua_gettop(L)<2 then
    luaL_error(L, 'sound.play expects 3 parameters (name, pos, paused).', [])
  else
    begin
if lua_gettop(l) >2 then
      v_paused := Lua_Toboolean(L, 3) else v_paused := false;
luapushsoundhandle(l, SoundSystem^.playSound3d(Lua_Tostring(L, 1), LuaToVector3F(l,2), v_paused));
    end;
  result := 1
end;

function luass_pauseAll(L: lua_state): Integer; cdecl;
var v_state:boolean;
begin
  if lua_gettop(L)<1 then
v_state := true else
      v_state := Lua_Toboolean(L, 1);
      SoundSystem^.pauseall(v_state);
  result := 0
end;

function luass_playSound3donce(L: lua_state): Integer; cdecl;
var
v_handle:soundhandle;
hh: soundhandle;
begin
  if lua_gettop(L)<3 then
    luaL_error(L, 'sound.playOnce expects 3 parameters (handle, name, pos).', [])
  else
begin
v_handle := luatosoundhandle(l,1);
hh := SoundSystem^.playSound3dOnce(v_handle, Lua_Tostring(L, 2), LuaToVector3F(l, 3));
if v_handle <> hh then
luapushsoundhandle(l, hh) else
lua_pop(l, lua_gettop(l) -1);
    end;
  result := 1
end;

    function luass_setlistenerpos(L: lua_state): Integer; cdecl;
begin
if Lua_GetTop(l) <>1 then
    luaL_error(L, 'listener.setPos expects 1 parameter (pos).', []);
SoundSystem^.setlistenerpos(LuaToVector3F(l,1));
  result := 0
end;

function luass_setlistenerorientation(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'listener.setOrientation expects 2 parameters (forward, top).', [])
  else
SoundSystem^.setlistenerorientation(LuaToVector3F(l,1), LuaToVector3F(l, 2));
  result := 0
end;

function luass_setsoundpos(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<2 then
    luaL_error(L, 'sound.setPos expects 3 parameters (sound, pos, HeadRelative).', [])
  else
      SoundSystem^.setsoundpos(luatosoundhandle(l,1), LuaToVector3F(l,2), LuaToBoolean(l,3));
  result := 0
end;

function luass_pausesound(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'sound.pause expects 2 parameters (s, state).', [])
  else
      SoundSystem^.pauseSound(luatosoundhandle(l, 1), Lua_Toboolean(L, 2));
  result := 0
end;

function luass_setsoundvelocity(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'sound.setVelocity expects 2 parameters (handle, vel).', [])
  else
      SoundSystem^.setsoundvelocity(luatosoundhandle(l, 1), LuaToVector3F(l,2));
  result := 0
end;

function luass_setlistenervelocity(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>1 then
    luaL_error(L, 'listener.setVelocity expects 1 parameter (vel).',[])
  else
      SoundSystem^.setlistenervelocity(LuaToVector3F(l,1));
  result := 0
end;

function luass_setsoundminmaxdistance(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>3 then
    luaL_error(L, 'sound.setMinMaxDistance expects 3 parameters (handle, min, max).', [])
  else
      SoundSystem^.setsoundminmaxdistance(luatosoundhandle(l, 1), lua_tonumber(L, 2), lua_tonumber(L, 3));
  result := 0
end;

function luass_isplaying(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>1 then
    luaL_error(L, 'sound.isPlaying expects 1 parameter (handle).', [])//123
  else
      Lua_Pushboolean(L, SoundSystem^.isplaying(luatosoundhandle(l, 1)));
  result := 1
end;

function luaGCSoundHandle(L: lua_State): Integer; cdecl;
begin
soundsystem^.stopsound(luatosoundhandle(l, 1));
result := 0;
end;
Function Luass_PlaySound2D(l:Lua_State):integer; cdecl;
var v_paused : boolean;
begin
  if lua_gettop(L)<1 then
    luaL_error(L, 'sound.play2D expects 2 parameters (name, paused).', [])
  else
    begin
if lua_gettop(l) >1 then
      v_paused := Lua_Toboolean(L, 2) else v_paused := false;
luapushsoundhandle(l, SoundSystem^.playSound2d(Lua_Tostring(L, 1), v_paused));
    end;
  result := 1
end;

Function Luass_PlaySound2DOnce(l:Lua_State):integer; cdecl;
var
v_handle:soundhandle;
hh: soundhandle;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'sound.play2DOnce expects 2 parameters (handle, name).', [])
  else
begin
v_handle := luatosoundhandle(l,1);
hh := SoundSystem^.playSound2DOnce(v_handle, Lua_Tostring(L, 2));
if v_handle <> hh then
luapushsoundhandle(l, hh) else
lua_pop(l, lua_gettop(l) -1);
    end;
  result := 1
end;
Function LuaSS_GetSoundFrequency(l:Lua_State):integer; cdecl;
begin
if lua_gettop(l) <> 1 then lual_error(l, 'sound.getFrequency expects 1 parameter (handle).', []);
Lua_PushNumber(l, soundSystem^.GetSoundFrequency(LuaToSoundHandle(l, 1)));
result:=1;
end;
Function LuaSS_SetSoundFrequency(l:Lua_State):integer; cdecl;
begin
if lua_gettop(l) <> 2 then lual_error(l, 'sound.setFrequency expects 2 parameters (handle, percent).', []);
SoundSystem^.setSoundFrequency(LuaToSoundHandle(l, 1), Lua_ToNumber(l, 2));
result:=0;
end;

function luaIndexSound(l:lua_state):integer; cdecl;
var s:string;
begin
s := lua_tostring(l, 2);
result:=1;
if s= 'play' then
lua_pushcfunction(l, luass_playsound3d) else
                                            if s = 'playOnce' then
lua_pushcfunction(l, luass_playsound3donce) else
if s= 'play2D' then
lua_pushcfunction(l, luass_playsound2d) else
                                            if s = 'play2DOnce' then
lua_pushcfunction(l, luass_playsound2donce) else
if s = 'getFrequency' then
lua_pushcfunction(l, Luass_GetSoundFrequency) else
if s = 'setFrequency' then
lua_pushcfunction(l, LuaSS_SetSoundFrequency) else
if s = 'pause' then
lua_pushcfunction(l, luass_pausesound) else
if s = 'setPos' then
lua_pushcfunction(l, luass_setsoundpos) else
if s = 'setVelocity' then
lua_pushcfunction(l, luass_setsoundvelocity) else
if s = 'isPlaying' then
lua_pushcfunction(l, luass_isplaying) else
if s = 'setMinMaxDistance' then
lua_pushcfunction(l, luass_setsoundminmaxdistance) else
if s = 'free' then
lua_pushcfunction(l, luagcsoundhandle) else
result := 0;
end;

procedure luaRegisterSoundHandle(l: lua_state);
begin
lual_newmetatable(l, 'soundHandle');
{lua_pushstring(l, '__gc');
lua_pushcfunction(l, luagcsoundhandle);
lua_rawset(l, -3);}
lua_pushstring(l, '__index');
lua_pushcfunction(l, luaindexsound);
lua_rawset(l, -3);
lua_pop(l, 1);
end;

function luaToGeometry(l:lua_state; i:integer):ss_geometry;
begin
result := ss_Geometry(lual_checkudata(l, i, 'geometry')^);
end;

procedure luaPushGeometry(l:lua_state; g:ss_geometry);
var p:^ss_geometry;
begin
p :=lua_newuserdata(l, sizeof(ss_geometry));
p^ := g;
lual_getmetatable(l, 'geometry');
lua_setmetatable(l, -2);
end;

function luaGCGeometry(L: lua_State): Integer; cdecl;
begin
SoundGeometry^.ReleaseGeometry(luatogeometry(l, 1));
result := 0
end;

function luass_createBox(L: lua_state): Integer; cdecl;
var
v_directOcclusion, v_reverbOcclusion:Single;
begin
  if lua_gettop(L)<2 then
    luaL_error(L, 'geometry.createBox expects 4 parameters (pos, size, directOcclusion, reverbOcclusion).', [])
  else
    begin
if lua_isnumber(l, 3) then v_directOcclusion := lua_tonumber(l, 3) else v_directOcclusion := 1;
if lua_isnumber(l, 4) then v_reverbOcclusion := lua_tonumber(l, 4) else v_reverbOcclusion := 0;
luapushgeometry(l, SoundGeometry^.createGeometryBox(LuaToVector3F(l, 1), LuaToVector3F(l, 2), v_directOcclusion, v_reverbOcclusion));
    end;
  result := 1
end;

function luass_togglegeometry(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'geometry.toggle expects 2 parameters (g, state).', [])
  else
      SoundGeometry^.togglegeometry(luatogeometry(l, 1), Lua_ToBoolean(L, 2));
  result := 0
end;

function luass_setGeometryPos(L: lua_state): Integer; cdecl;
begin
  if lua_gettop(L)<>2 then
    luaL_error(L, 'geometry.setPos expects 2 parameters (g, pos).', [])
  else
      SoundGeometry^.setGeometryPos(luatogeometry(l, 1), LuaToVector3F(l,2));
  result := 0
end;

function Luass_SetGeometryWorldSize(l:lua_state):integer; cdecl;
begin
if lua_gettop(l) <> 1 then
lual_error(l, 'geometry.setWorldSize expects 1 parameter (size).', []) else
soundGeometry^.SetGeometryWorldSize(Lua_ToNumber(l, 1));
result:=0;
          end;
function luaIndexGeometry(l:lua_state):integer; cdecl;
var s:string;
begin
result:=1;
             s := lua_tostring(l, 2);
if s = 'setPos' then
lua_pushcfunction(l, luass_setgeometrypos) else
if s = 'toggle' then
lua_pushcfunction(l, luass_togglegeometry) else
if s = 'free' then
lua_pushcfunction(l, luagcgeometry) else
result:=0;
end;

                   procedure luaRegisterGeometry(l:lua_state);
begin
lual_newmetatable(l, 'geometry');
lua_pushstring(l, '__gc');
lua_pushcfunction(l, luagcgeometry);
lua_rawset(l, -3);
lua_pushstring(l, '__index');
lua_pushcfunction(l, luaindexgeometry);
lua_rawset(l, -3);
lua_pop(l, 1);
end;

Function LuaSS_SetAmbientReverb(l:lua_state):integer; cdecl;
begin
result:=0;
if lua_gettop(l) <>1 then lual_error(l, 'reverb.setAmbientReverb expects 1 parameter (reverb).', [])
else Reverb^.SetAmbientReverb(lua_tostring(l,1));
end;
    Function LuaReverbCreate(l:lua_state):integer; cdecl;
    begin
if lua_gettop(l) <> 4 then lual_error(l, 'reverb.create expects 4 parameters (name, pos, min, max).', []);
lua_pushLightUserData(l, reverb^.createReverb(lua_tostring(l, 1), luaToVector3F(l, 2), lua_tonumber(l, 3), lua_tonumber(l, 4)));
result:=1;
    end;

    Procedure RegisterSoundSystem;
    begin
SoundSystem:=Core_RequirePlugin(SoundSystemI.SoundSystemGUID);
LuaRegisterSoundHandle(l);
luaRegister(l, 'sound.play', luass_playSound3d);
luaRegister(l, 'sound.play2D', luass_playSound2d);
luaRegister(l, 'sound.playOnce', luass_playSound3donce);
luaRegister(l, 'sound.play2DOnce', luass_playSound2DOnce);
luaRegister(l, 'listener.setPos', luass_setlistenerpos);
luaRegister(l, 'listener.setOrientation', luass_setlistenerorientation);
luaRegister(l, 'sound.setPos', luass_setsoundpos);
luaRegister(l, 'sound.pause', luass_pausesound);
luaRegister(l, 'sound.setVelocity', luass_setsoundvelocity);
luaRegister(l, 'listener.setVelocity', luass_setlistenervelocity);
luaRegister(l, 'sound.setMinMaxDistance', luass_setsoundminmaxdistance);
luaRegister(l, 'sound.isPlaying', luass_isplaying);
luaRegister(l, 'sound.free', luagcsoundhandle);
LuaRegister(l, 'sound.getFrequency', LuaSS_GetSoundFrequency);
                                                              LuaRegister(l, 'sound.setFrequency', LuaSS_setSoundFrequency);
luaRegister(l, 'sound.pauseAll', luass_pauseAll);
    end;

    Procedure RegisterSoundGeometry;
    begin
SoundGeometry:=Core_RequirePlugin(SoundSystemI.SoundGeometryGUID);
    LuaRegisterGeometry(l);
    luaRegister(l, 'geometry.createBox', luass_createBox);
luaRegister(l, 'geometry.toggle', luass_togglegeometry);
luaRegister(l, 'geometry.setPos', luass_setgeometrypos);
luaRegister(l, 'geometry.free', luagcgeometry);
LuaRegister(l, 'geometry.setWorldSize', luass_SetGeometryWorldSize);
    end;

    procedure RegisterReverb;
    begin
Reverb:=Core_RequirePlugin(SoundSystemI.ReverbGUID);
    LuaRegister(l, 'reverb.setAmbientReverb', luaSS_SetAmbientReverb);
luaRegister(l, 'reverb.create', LuaReverbCreate);
            end;
